package com.pj.lib.auraServer.app;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.pj.lib.aura.connection.AuraTypeModel;
import com.pj.lib.aura.connection.LocationModel;
import com.pj.lib.auraServer.app.listeners.OnAuraTypesChange;

import com.pj.lib.auraServer.app.listeners.OnAuraEvent;
import com.pj.lib.auraServer.app.listeners.OnAuraTypesChanged;
import com.pj.lib.auraServer.app.listeners.OnLocationUpdate;
import com.pj.lib.auraServer.app.listeners.OnLocationUpdated;
import com.pj.lib.auraServer.app.listeners.OnUserChange;
import com.pj.lib.auraServer.app.listeners.OnUserChanged;
import com.pj.lib.auraServer.components.DB.DB;
import com.pj.lib.auraServer.components.DB.DBComponent;
import com.pj.lib.auraServer.components.connection.ClientThread;


public abstract class ServerComponent {
	private Server server;
	public final static int COMPONENT_NETWORK_MANAGER = 1;
	public final static int COMPONENT_DB = 2;
	public final static int COMPONENT_LBS = 3;
	public final static int COMPONENT_LOCATION_PROPAGATION = 4;
	public final static int COMPONENT_AURA_TYPE = 5;
	public final static int COMPONENT_AURA_EVENTS = 6;
	public final static int COMPONENT_USER_AURA_CONNECTION = 7;
	public final static int COMPONENT_USER_MANAGEMENT = 8;
	
	
	private List<OnLocationUpdate> mOnLocationUpdateListeners = new ArrayList<OnLocationUpdate>();
	private List<OnLocationUpdated> mOnLocationUpdatedListeners = new ArrayList<OnLocationUpdated>();
	private List<OnUserChange> mOnUserChangeListeners = new ArrayList<OnUserChange>();
	private List<OnUserChanged> mOnUserChangedListeners = new ArrayList<OnUserChanged>();
	private List<OnAuraTypesChange> mOnAuraTypeChangeListeners = new ArrayList<OnAuraTypesChange>();
	private List<OnAuraTypesChanged> mOnAuraTypeChangedListeners = new ArrayList<OnAuraTypesChanged>();
	private List<OnAuraEvent> mOnAuraEventListeners = new ArrayList<OnAuraEvent>();
	
	
	public ServerComponent(Server server) {
		this.server = server;
	}
	
	public Server getServer() {
		return this.server;
	}
	
	public  void removeOnUpdateLocation(OnLocationUpdate listener) {
		server.removeOnUpdateLocation(listener);
	}
	
	/**
	 * Adding OnUpdateLocation listener - it is fired when system gets new location 
	 * @param listener
	 */
	public  void addOnUpdateLocation(OnLocationUpdate listener) {
		server.addOnUpdateLocation(listener);
	}
	
	public  void removeOnLocationUpdated(OnLocationUpdated listener) {
		server.removeOnLocationUpdated(listener);
	}
	
	/**
	 * Adding OnUpdatedLocation listener - it is fired after location db changed
	 * @param listener
	 */
	public  void addOnLocationUpdated(OnLocationUpdated listener) {
		server.addOnLocationUpdated(listener);
	}
	
	
	public  void removeOnUserChange(OnUserChange listener) {
		server.removeOnUserChange(listener);
	}
	
	/**
	 * Adding OnUserChange listener - it is fired when system gets user change 
	 * @param listener
	 */
	public  void addOnUserChange(OnUserChange listener) {
		server.addOnUserChange(listener);
	}
	
	public  void removeOnUserChanged(OnUserChanged listener) {
		server.removeOnUserChanged(listener);
	}
	
	/**
	 * Adding OnUserChange listener - it is fired when system gets user change 
	 * @param listener
	 */
	public  void addOnUserChanged(OnUserChanged listener) {
		server.addOnUserChanged(listener);
	}
	
	public  void removeOnAuraTypeChange(OnAuraTypesChange listener) {
		server.removeOnAuraTypeChange(listener);
	}
	
	/**
	 * Adding OnAuraTypeChange listener - it is fired when system gets aura type change 
	 * @param listener
	 */
	public  void addOnAuraTypeChange(OnAuraTypesChange listener) {
		server.addOnAuraTypeChange(listener);
	}
	
	public  void removeOnAuraTypeChanged(OnAuraTypesChanged listener) {
		server.removeOnAuraTypeChanged(listener);
	}
	
	/**
	 * Adding OnAuraTypeChange listener - it is fired when system gets aura type change 
	 * @param listener
	 */
	public  void addOnAuraTypeChanged(OnAuraTypesChanged listener) {
		server.addOnAuraTypeChanged(listener);
	}
	
	
	public  void removeOnAuraEvent(OnAuraEvent listener) {
		server.removeOnAuraEvent(listener);
	}
	
	/**
	 * Adding OnAuraTypeChange listener - it is fired when system gets aura type change 
	 * @param listener
	 */
	public  void addOnAuraEvent(OnAuraEvent listener) {
		server.addOnAuraEvent(listener);
	}
	
	
	/**
	 * Fires {@link OnLocationUpdate#locationReceived(int, double[], float)} event
	 * @param userId
	 * @param loc
	 * @param precision
	 */
	public void fireLocationUpdateEvent(int userId, double[] loc, float precision) {
		server.fireLocationUpdateEvent(userId, loc, precision);
	}
	
	/**
	 * Fires {@link OnLocationUpdated#locationUpdated()} event
	 */
	public void fireLocationUpdatedEvent(LocationModel location) {
		server.fireLocationUpdatedEvent(location);
		
	}
	
	/**
	 * Fires {@link OnUserChange#userLogin(ClientThread, String, String)} event
	 * @param ct
	 * @param username
	 * @param password
	 */
	public void fireUserLoginEvent(ClientThread ct, String username, String password) {
		server.fireUserLoginEvent(ct, username, password);
		
	}
	
	/**
	 * Fires {@link OnUserChanged#userLogged(int)} event
	 * @param userId
	 */
	public void fireUserLoggedEvent(int userId) {
		server.fireUserLoggedEvent(userId);

	}
	/**
	 * Fires {@link OnUserChange#userLogout(int)} event
	 * @param userId
	 */
	public void fireUserLogoutEvent(int userId) {
		server.fireUserLogoutedEvent(userId);

	}
	
	/**
	 * Fires {@link OnUserChanged#userLogouted(int)} event
	 * @param userId
	 */
	public void fireUserLogoutedEvent(int userId) {
		server.fireUserLogoutedEvent(userId);

	}
	
	/**
	 * Fires {@link OnUserChange#userCreate(ClientThread, String, String)} event
	 * @param ct
	 * @param username
	 * @param password
	 */
	public void fireUserCreateEvent(ClientThread ct, String username, String password) {
		server.fireUserCreateEvent(ct, username, password);
		
	}

	/**
	 * Fires {@link OnUserChanged#userCreated(int)} event
	 * @param userId
	 */
	public void fireUserCreatedEvent(int userId) {
		server.fireUserCreatedEvent(userId);
	}
	/**
	 * Fires {@link OnAuraTypesChange#addAuraTypes(ClientThread, AuraTypeModel[])} event
	 * @param ct
	 * @param auraTypes
	 */
	public void fireAuraTypesAddEvent(ClientThread ct, AuraTypeModel[] auraTypes) {
		server.fireAuraTypesAddEvent(ct, auraTypes);

	}
	
	/**
	 * Fires {@link OnAuraTypesChanged#auraTypesAdded()} event
	 */
	public void fireAuraTypesAddedEvent(AuraTypeModel[] auraTypes) {
		server.fireAuraTypesAddedEvent(auraTypes);
	}
	/**
	 * Fires {@link OnAuraTypesChange#updateAuraType(ClientThread, AuraTypeModel, String)} event
	 * @param ct
	 * @param auraType
	 * @param code
	 */
	public void fireAuraTypeUpdateEvent(ClientThread ct, AuraTypeModel auraType, String code) {
		server.fireAuraTypeUpdateEvent(ct, auraType, code);
	}
	
	/**
	 * Fires {@link OnAuraTypesChanged#auraTypeUpdated()} event
	 */
	public void fireAuraTypeUpdatedEvent(AuraTypeModel type) {
		server.fireAuraTypeUpdatedEvent(type);
	}
	/**
	 * Fires {@link OnAuraTypesChange#deleteAuraType(ClientThread, String, String)} event
	 * @param ct
	 * @param code
	 * @param replacementCode
	 */
	public void fireAuraTypeDeleteEvent(ClientThread ct, String code, String replacementCode) {
		server.fireAuraTypeDeleteEvent(ct, code, replacementCode);
	}
	
	/**
	 * Fires {@link OnAuraTypesChanged#auraTypeDeleted()} event
	 */
	public void fireAuraTypeDeletedEvent(String code) {
		server.fireAuraTypeDeletedEvent(code);
	}
	/**
	 * Fires {@link OnUserChange#deleteAuraType(ClientThread, String, String)} event
	 * @param ct
	 * @param code
	 */
	public void fireAuraTypeGetEvent(ClientThread ct, String code) {
		Server.debug("sending get aura type event. Number of listeners: " 
				+ mOnAuraTypeChangeListeners.size());
		server.fireAuraTypeGetEvent(ct, code);
	}
	
	/**
	 * Fires {@link OnUserChange#setAura(ClientThread, String, int)} event
	 * @param ct
	 * @param code
	 * @param userId
	 */
	public void fireUserAuraSetEvent(ClientThread ct, String code, int userId) {
		server.fireUserAuraSetEvent(ct, code, userId);
	}
	
	/**
	 * Fires {@link OnUserChanged#auraSet(int)} event
	 * @param userId
	 */
	public void fireAfterUserAuraSetEvent(int userId, String auraCode) {
		server.fireAfterUserAuraSetEvent(userId, auraCode);
	}
	
	/**
	 * Fires {@link OnUserChange#disableAura(ClientThread, int)} event
	 * @param ct
	 * @param userId
	 */
	public void fireUserAuraDisableEvent(ClientThread ct, int userId) {
		server.fireUserAuraDisableEvent(ct, userId);
	}
	
	/**
	 * Fires {@link OnUserChanged#auraDisabled(int)} event
	 * @param userId
	 */
	public void fireUserAuraDisabledEvent(int userId) {
		server.fireUserAuraDisabledEvent(userId);

	}
	
	/**
	 * Fires {@link OnAuraEvent#enteredAura(int, int, String)} event
	 * @param userId
	 */
	public void fireEnteredAuraEvent(int acId, int asuId, String action) {
		server.fireEnteredAuraEvent(acId, asuId, action);
	}
	
	/**
	 * Fires {@link OnAuraEvent#leftAura(int, int, String)} event
	 * @param userId
	 */
	public void fireLeftAuraEvent(int acId, int asuId, String action) {
		server.fireLeftAuraEvent(acId, asuId, action);
	}
	
	/**
	 * Fires {@link OnAuraEvent#temporaryLeftAura(int, int, String)} event
	 * @param userId
	 */
	public void fireTemporaryLeftAuraEvent(int acId, int asuId, String action) {
		server.fireTemporaryLeftAuraEvent(acId, asuId, action);
	}
	
	/**
	 * Fires {@link OnAuraEvent#temporaryLeftAura(int, int, String)} event
	 * @param userId
	 */
	public void fireReturnFromTemporaryLeftAuraAuraEvent(int acId, int asuId, String action) {
		server.fireReturnFromTemporaryLeftAuraAuraEvent(acId, asuId, action);
	}
	
	
	
	
	
	
	/**
	 * Gets DB instance. Also DB instance can be returned by ((DBComponent)getServer().getComponent(COMPONENT_DB)).getDB();
	 * @return DB instance
	 */
	protected DB getDB() {
		return ((DBComponent)getServer().getComponent(COMPONENT_DB)).getDB();
	}
}
